package com.lhkj.ct.meta.modules.patient.service;


import com.lhkj.ct.base.constants.DictConstants;
import com.lhkj.ct.base.constants.SystemConstants;
import com.lhkj.ct.base.exception.ValidatedException;
import com.lhkj.ct.base.model.Option;
import com.lhkj.ct.base.utils.ShiroUtil;
import com.lhkj.ct.base.utils.StringUtil;
import com.lhkj.ct.base.utils.file.excel.ExcelUtils;
import com.lhkj.ct.meta.admin.service.SysDictDataService;
import com.lhkj.ct.meta.modules.common.enums.PatientModule;
import com.lhkj.ct.meta.modules.patient.model.dto.ImportPatientDto;
import com.lhkj.ct.meta.modules.patient.model.entity.TblPatient;
import com.lhkj.ct.meta.modules.psychology.model.bo.PatientItem;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.DefaultIndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import java.util.*;
import java.util.stream.Collectors;

/**
  * <p>
  *     描述：档案模板导出
  * </p>
  */
@Service
public class ArchiveModuleProcess {

    @Resource
    private SysDictDataService sysDictDataService;

    @Resource
    private PatientService patientService;

    @Resource
    private Validator validator;

    public Workbook generateTemplate() {
        // 创建 excel 工作簿
        SXSSFWorkbook wb = new SXSSFWorkbook();
        // 创建sheet
        SXSSFSheet sheet = wb.createSheet("sheet");
        // 设置自动换行
        sheet.setAutobreaks(true);
        // 锁定sheet
        sheet.protectSheet("password");
        // 设置默认列宽
        sheet.setDefaultColumnWidth(20);
        sheet.setDefaultRowHeight((short) (2*256));
        // 表头
        SXSSFRow tableHeader = sheet.createRow(0);
        // 生成下拉框
        DataValidationHelper helper = sheet.getDataValidationHelper();
        XSSFCellStyle header_style = (XSSFCellStyle) wb.createCellStyle();
        header_style.setBorderTop(BorderStyle.THIN);// 上边框
        header_style.setBorderRight(BorderStyle.THIN);// 右边框
        header_style.setBorderBottom(BorderStyle.THIN); // 下边框
        header_style.setBorderLeft(BorderStyle.THIN);// 左边框
        header_style.setVerticalAlignment(VerticalAlignment.CENTER);
        header_style.setAlignment(HorizontalAlignment.CENTER);
        // 设置边框
        CellStyle border_unlocked = wb.createCellStyle();
        border_unlocked.cloneStyleFrom(header_style);
        border_unlocked.setLocked(false);
        CellStyle date_style = wb.createCellStyle();
        date_style.cloneStyleFrom(border_unlocked);
        CellStyle text_style = wb.createCellStyle();
        text_style.cloneStyleFrom(border_unlocked);
        header_style.setFillPattern(FillPatternType.SOLID_FOREGROUND);//填充模式
        header_style.setFillForegroundColor(new XSSFColor(new java.awt.Color(216, 216, 216, 50), new DefaultIndexedColorMap()));//设置背景色
        List<PatientItem> archiveModuleList = Arrays.stream(PatientModule.values()).map(PatientModule::getItem).collect(Collectors.toList());
        for (int i = 0; i < archiveModuleList.size(); i++) {
            sheet.setDefaultColumnStyle(i, border_unlocked);
            // 模板
            PatientItem archiveModule = archiveModuleList.get(i);
            SXSSFCell cell = tableHeader.createCell(i);
            cell.setCellValue(archiveModule.getLabel());
            cell.setCellStyle(header_style);
            if (StringUtils.equals(archiveModule.getType(), "select") && StringUtils.isNotBlank(archiveModule.getDictCode())){
                // 数据字典下拉框
                String[] dropDownData = sysDictDataService.selectDictDataByType(archiveModule.getDictCode()).stream().map(Option::getLabel).toArray(String[]::new);
                ExcelUtils.setRadioValidation(sheet, helper, dropDownData, 1, SpreadsheetVersion.EXCEL2007.getLastRowIndex(), i, i);
            }else if (StringUtils.equals(archiveModule.getType(), "date")){
                // 日期格式
                DataFormat dataFormat = wb.createDataFormat();
                String format = StringUtils.defaultIfEmpty(archiveModule.getFormat(), "yyyy-MM-dd");
                date_style.setDataFormat(dataFormat.getFormat(format));
                sheet.setDefaultColumnStyle(i, date_style);
                ExcelUtils.setDateValidation(sheet,
                        helper,
                        format,
                        new CellRangeAddressList(1, SpreadsheetVersion.EXCEL2007.getLastRowIndex(), i, i));
            }else{
                // 普通文本
                DataFormat format = wb.createDataFormat();
                text_style.setDataFormat(format.getFormat("@"));
                text_style.setLocked(false);
                sheet.setDefaultColumnStyle(i, text_style);
            }
        }
        return wb;
    }

    public void importArchives(ImportPatientDto importDto) {
        Map<String, String> gender = sysDictDataService.selectDictDataByType(DictConstants.GENDER).stream().collect(Collectors.toMap(Option::getLabel, Option::getValue));
        Map<String, String> indentType = sysDictDataService.selectDictDataByType(DictConstants.IDENT_TYPE).stream().collect(Collectors.toMap(Option::getLabel, Option::getValue));
        Map<String, String> nation = sysDictDataService.selectDictDataByType(DictConstants.NATION).stream().collect(Collectors.toMap(Option::getLabel, Option::getValue));
        Map<String, String> education = sysDictDataService.selectDictDataByType(DictConstants.EDUCATION).stream().collect(Collectors.toMap(Option::getLabel, Option::getValue));
        Map<String, String> marriage = sysDictDataService.selectDictDataByType(DictConstants.MARRIAGE).stream().collect(Collectors.toMap(Option::getLabel, Option::getValue));
        List<TblPatient> patients = new ArrayList<>();
        if (Objects.equals(2, importDto.getPwdPolicy())) {
            String pwd = new Md5Hash(importDto.getPwd(), SystemConstants.ACCOUNT_SALT, SystemConstants.HASH_ITERATIONS).toHex();
            importDto.setPwd(pwd);
        }
        String userId = ShiroUtil.getAuthUserInfo().getUserId();
        for (ImportPatientDto.PatientInfo patientInfo : importDto.getPatientInfos()) {
            Set<ConstraintViolation<ImportPatientDto.PatientInfo>> validate =
                    validator.validate(patientInfo, Objects.equals(2, importDto.getAccountPolicy()) ?
                            new Class[]{ImportPatientDto.Patient.class, ImportPatientDto.Phone.class} : new Class[]{ImportPatientDto.Patient.class});
            if (!validate.isEmpty()) {
                throw new ConstraintViolationException(validate);
            }
            if (!gender.containsKey(patientInfo.getPatSex())) {
                throw new ValidatedException(String.format("第%d条数据性别不合法", patientInfo.getIxh()));
            }
            patientInfo.setPatSex(gender.get(patientInfo.getPatSex()));
            if (!indentType.containsKey(patientInfo.getPatIdentType())) {
                throw new ValidatedException(String.format("第%d条数据证件类型不合法", patientInfo.getIxh()));
            }
            patientInfo.setPatIdentType(indentType.get(patientInfo.getPatIdentType()));
            if (StringUtils.isNotBlank(patientInfo.getPatNation())) {
                if (!nation.containsKey(patientInfo.getPatNation())) {
                    throw new ValidatedException(String.format("第%d条数据民族不合法", patientInfo.getIxh()));
                }
                patientInfo.setPatNation(gender.get(patientInfo.getPatNation()));
            }
            if (StringUtils.isNotBlank(patientInfo.getPatEducation())) {
                if (!education.containsKey(patientInfo.getPatEducation())) {
                    throw new ValidatedException(String.format("第%d条数据学历不合法", patientInfo.getIxh()));
                }
                patientInfo.setPatEducation(gender.get(patientInfo.getPatEducation()));
            }
            if (StringUtils.isNotBlank(patientInfo.getPatMarriage()) ) {
                if (marriage.containsKey(patientInfo.getPatMarriage())) {
                    throw new ValidatedException(String.format("第%d条数据婚姻状况不合法", patientInfo.getIxh()));
                }
                patientInfo.setPatMarriage(gender.get(patientInfo.getPatMarriage()));
            }
            TblPatient patient = patientInfo.build();
            if (Objects.equals(1, importDto.getAccountPolicy())){
                patient.setAccount(patientInfo.getPatIdentNo());
            } else if (Objects.equals(2, importDto.getAccountPolicy())) {
                patient.setAccount(patientInfo.getPatMobile());
            }
            if (Objects.equals(1, importDto.getPwdPolicy())){
                String originalPwd = StringUtil.subAfter(patientInfo.getPatIdentNo(), 6);
                String pwd = new Md5Hash(originalPwd, SystemConstants.ACCOUNT_SALT, SystemConstants.HASH_ITERATIONS).toHex();
                patient.setPassword(pwd);
            } else if (Objects.equals(2, importDto.getPwdPolicy())) {
                patient.setPassword(importDto.getPwd());
            }
            patient.setCreateBy(userId);
            patients.add(patient);
        }
        patientService.batchCreate(patients);
    }
}
